﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using MathematicallySafe.HeadCounter.Data.Common;
using MathematicallySafe.HeadCounter.Data.Domain;
using MathematicallySafe.HeadCounter.Data.Interfaces;
using StructureMap;

namespace MathematicallySafe.HeadCounter.Data.Models
{
    [Serializable]
    public class RaidHistoryModel : IRaidHistory
    {
        private bool _isDirty;
        private RaidHistory _raidHistory;

        private SerializableSortedList<DateTime, Raid> RaidsDictionary
        {
            get { return _raidHistory.RaidsDictionary; }
        }

        public DateTime WeekOneDate
        {
            get { return _raidHistory.WeekOneDate; }
            set { _raidHistory.WeekOneDate = value; }
        }

        public RaidHistoryModel()
        {
            if (File.Exists(Constants.GuildFileName))
            {
                Load();
            }
            else
            {
                CreateDefault();
            }
        }

        private void CreateDefault()
        {
            _raidHistory = new RaidHistory
                               {
                                   RaidsDictionary = new SerializableSortedList<DateTime, Raid>()
                               };
        }

        #region Raids

        public IEnumerable<Raid> Raids
        {
            get { return RaidsDictionary.Values; }
        }

        public bool HasRaids
        {
            get { return RaidsDictionary.Count() > 0; }
        }

        public void AddRaid(Raid raid)
        {
            if (RaidsDictionary.Count == 0)
            {
                SetStartWeek(raid.Date);
            }

            if (!RaidsDictionary.ContainsKey(raid.Date))
            {
                RaidsDictionary.Add(raid.Date, raid);
                OnRaidAdded(new RaidsHistoryChangedEventArgs(raid));
            }
        }

        public void RemoveRaid(Raid raid)
        {
            if (RaidsDictionary.ContainsKey(raid.Date))
            {
                RaidsDictionary.Remove(raid.Date);
                OnRaidRemoved(new RaidsHistoryChangedEventArgs(raid));
            }
        }

        #endregion

        #region Events

        public event EventHandler<RaidsHistoryChangedEventArgs> RaidAdded;
        public event EventHandler<RaidsHistoryChangedEventArgs> RaidRemoved;

        protected virtual void OnRaidAdded(RaidsHistoryChangedEventArgs e)
        {
            if (RaidAdded != null)
            {
                RaidAdded(this, e);
            }
        }

        protected virtual void OnRaidRemoved(RaidsHistoryChangedEventArgs e)
        {
            if (RaidRemoved != null)
            {
                RaidRemoved(this, e);
            }
        }

        #endregion

        #region Dates

        private void SetStartWeek(DateTime firstRaidDate)
        {
            WeekOneDate = firstRaidDate.GetWeekStart(ObjectFactory.GetInstance<IOptions>().Region);
        }

        public int LatestRaidWeek
        {
            get
            {
                var lastRaid = RaidsDictionary.Last().Value;
                return lastRaid.Date.GetWeekNumber();
            }
        }

        #endregion

        #region IPersistable

        public bool IsDirty
        {
            get { return _isDirty; }
        }

        public bool IsClean
        {
            get { return !_isDirty; }
        }

        public void SetClean()
        {
            _isDirty = false;
        }

        public void SetDirty()
        {
            _isDirty = true;
        }

        private void Load()
        {
            _raidHistory = SerialisationHelper.Load<RaidHistory>(Constants.RaidsFileName);
        }

        public void Save()
        {
            SerialisationHelper.Save(Constants.RaidsFileName, _raidHistory);
        }

        #endregion

    }

    public class RaidsHistoryChangedEventArgs : EventArgs
    {
        public readonly Raid Raid;

        public RaidsHistoryChangedEventArgs(Raid raid)
        {
            Raid = raid;
        }
    }
}